using System;
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using Object = UnityEngine.Object;

public class map : MonoBehaviour
{
    public static map Instance;
    public Transform canvasRoot;
    public EvaluationFunctionType EvaluationFunctionType;

    public List<AStarNode> grideList = new List<AStarNode>();


    private Dictionary<AStarNode, AStarNodeMono> cubeDic = new Dictionary<AStarNode, AStarNodeMono>();

    public GameObject nodePrefab;

    private float unitSize = 100;
    public Vector2Int mapSize = new Vector2Int(100, 100);

    private AStar _aStar = new AStar();

    public Transform player;
    public Transform target;

    private void Awake()
    {
        Instance = this;
    }

    // Start is called before the first frame update
    void Start()
    {
        GenMap();
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            StartFindPath();
        }
    }

    /// <summary>
    /// 开始寻路
    /// </summary>
    public void StartFindPath()
    {
        ClearState();

        Debug.Log("开始寻路...");

        var startPoint = GetAstarPosByLocalPos(player.localPosition);
        var endPoint = GetAstarPosByLocalPos(target.localPosition);

        Debug.Log($"起始点坐标 {startPoint}");
        Debug.Log($"目标点坐标 {endPoint}");
        StartCoroutine(_aStar.FindPath(grideList, startPoint, endPoint, EvaluationFunctionType, (b) =>
        {
            if (b)
            {
                Debug.Log("寻路成功");
                var endNode = _aStar.GetNodeByPos(endPoint.x, endPoint.y);
                if (endNode != null)
                {
                    DrawPath(endNode);
                }
            }
        }));
    }

    private void DrawPath(AStarNode endPoint)
    {
        if (endPoint == null) return;
        if (endPoint.parent != null)
        {
            DrawNodeColor(endPoint.parent, Color.green);
            DrawPath(endPoint.parent);
        }
    }

    private Vector2Int GetAstarPosByLocalPos(Vector3 pos)
    {
        return new Vector2Int(Mathf.FloorToInt(pos.x / unitSize), Mathf.FloorToInt(pos.y / unitSize));
    }

    private AStarNodeMono GetCubeByNode(AStarNode node)
    {
        cubeDic.TryGetValue(node, out AStarNodeMono obj);

        return obj;
    }

    /// <summary>
    /// 生成map
    /// </summary>
    private void GenMap()
    {
        for (int i = 0; i < mapSize.x; i++)
        {
            for (int j = 0; j < mapSize.y; j++)
            {
                var item = Object.Instantiate(nodePrefab, canvasRoot);
                //item.transform.localScale = Vector3.one * (ceilSize - 0.1f);
                item.transform.localPosition = new Vector3(i * unitSize,  j * unitSize,0);
                var starNode = new AStarNode() { pos = new Vector2Int(i, j) };
                grideList.Add(starNode);
                var starMono = item.GetComponent<AStarNodeMono>();
                starMono.node = starNode;
                cubeDic.Add(starNode, starMono);
            }
        }
    }

    private void ClearState()
    {
        foreach (var obj in cubeDic)
        {
            if (!obj.Key.isBlock)
            {
                obj.Value.ResetColor();
            }
        }
    }

    public void DrawNodeColor(AStarNode endPoint, Color color)
    {
        var nodeObj = GetCubeByNode(endPoint);
        if (nodeObj != null)
        {
            nodeObj.SetColor(color);
        }
    }

    public void SetGHF(AStarNode endPoint, int g, int h, int f, Vector2Int dir, bool isChange = false)
    {
        var nodeObj = GetCubeByNode(endPoint);
        if (nodeObj != null)
        {
            nodeObj.SetGHF(g, h, f, dir, isChange);
        }
    }
}